package br.ufrj.dcc.trabxml.manager;

import java.io.IOException;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Node;

import br.ufrj.dcc.trabxml.IdGenerator;
import br.ufrj.dcc.trabxml.util.Properties;
import br.ufrj.dcc.trabxml.util.TrabUtil;
import br.ufrj.dcc.trabxml.util.XmlUtil;

public class XmlManager {

    private static final String MESSAGE_SCHEMA_URL = "http://www.dcc.ufrj.br/~braganholo/disciplinas/mab617/trabalho/mensagem.xsd";
    //private static final String PUBLIC_MESSAGE_SCHEMA_URL = "http://lens-ese.cos.ufrj.br/~artur/mensagem.xsd";//copia para quando o dcc tiver fora
    
    private static final String PUBLIC_REQUEST_SCHEMA_URL = "http://www.dcc.ufrj.br/~braganholo/disciplinas/mab617/trabalho/solicitacao.xsd";
    
    private static final String PUBLIC_CATALOG_SCHEMA_URL = "http://www.dcc.ufrj.br/~braganholo/disciplinas/mab617/trabalho/catalogo.xsd";    
    
    private static final String PUBLIC_TO_INTERNAL_XSLT_URL = "xslt/public_to_internal.xslt";
    
    private static final String INTERNAL_TO_PUBLIC_XSLT_URL = "xslt/internal_to_public.xslt";        
    
    private static String internal_to_public_xslt = null;
    
    public static String transformToPublicXML(String internalXML) throws IOException {
        if (internal_to_public_xslt == null) {
            internal_to_public_xslt = TrabUtil.readTextFile(INTERNAL_TO_PUBLIC_XSLT_URL);
        }
        return XmlUtil.transformXML(internalXML,internal_to_public_xslt);
    }
    
    private static String public_to_internal_xslt = null;
    
    public static String transformToInternalXML(String publicXML) throws IOException {
        if (public_to_internal_xslt == null) {
            public_to_internal_xslt = TrabUtil.readTextFile(PUBLIC_TO_INTERNAL_XSLT_URL);
        }
        return XmlUtil.transformXML(publicXML,public_to_internal_xslt);
    }
    
    private static String message_schema = null;
    
    public static boolean validateMessageXML(String publicXML) throws IOException {
        if (message_schema == null) {
            message_schema = TrabUtil.getStringFromURL(MESSAGE_SCHEMA_URL);
        }
        return XmlUtil.validate(publicXML, message_schema);
    }
    
    private static String public_request_schema = null;
    
    public static boolean validatePublicRequestXML(String publicXML) throws IOException {
        if (public_request_schema == null) {
            public_request_schema = TrabUtil.getStringFromURL(PUBLIC_REQUEST_SCHEMA_URL);
        }
        return XmlUtil.validate(publicXML, public_request_schema);
    }    
    
    private static String public_catalog_schema = null;
    
    public static boolean validatePublicCatalogXML(String publicXML) throws IOException {
        if (public_catalog_schema == null) {
            public_catalog_schema = TrabUtil.getStringFromURL(PUBLIC_CATALOG_SCHEMA_URL);
        }
        return XmlUtil.validate(publicXML, public_catalog_schema);
    }        
    
    public static boolean validatePublicXML(String publicXML) throws IOException {
        return validateMessageXML(publicXML) || validatePublicRequestXML(publicXML) || validatePublicCatalogXML(publicXML);
    }

    public static String createCatalogRequest(int group) {
        return "<mensagem remetente='"
                + Properties.instance.getProperty("mygroup")
                + "' destinatario='" + group + "' id='"
                + IdGenerator.create().toString() + "'>"
                + "     <solicitacao tipo='catalogo' />" + "</mensagem>";
    }
    
    public static String createLendRequest(int group, int owner, String isbn) {
        return
        "<solicitacao id=\""+IdGenerator.create().toString()+"\">"+
            "<emprestimo>"+
                "<de>"+Properties.instance.getProperty("mygroup")+"</de>"+
                "<para>"+group+"</para>"+
                "<livro>"+
                    "<dono>"+owner+"</dono>"+
                    "<isbn>"+isbn+"</isbn>"+
                "</livro>"+
            "</emprestimo>" +
        "</solicitacao>";
    } 
    
    public static String createReturnRequest(int group, int owner, String isbn) {
        return
        "<solicitacao id=\""+IdGenerator.create().toString()+"\">"+
            "<devolucao>"+
                "<de>"+Properties.instance.getProperty("mygroup")+"</de>"+
                "<para>"+group+"</para>"+
                "<livro>"+
                    "<dono>"+owner+"</dono>"+
                    "<isbn>"+isbn+"</isbn>"+
                "</livro>"+
            "</devolucao>" +
        "</solicitacao>";
    }     
    
    public static boolean isCatalogRequest(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return xpath.evaluate("/mensagem/solicitacao[@tipo = 'catalogo']", root,XPathConstants.NODE) != null;
        } catch (Exception e) {
            return false;
        }
    }
    
    public static boolean isCatalog(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return xpath.evaluate("/catalogo", root,XPathConstants.NODE) != null;
        } catch (Exception e) {
            return false;
        }        
    }
    
    public static long getCatalogOwner(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return Long.parseLong(((Node)xpath.evaluate("/catalogo/@dono", root,XPathConstants.NODE)).getNodeValue());
        } catch (Exception e) {
            return 0;
        }         
    }
    
    public static long getMessageReceiver(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return Long.parseLong(((Node)xpath.evaluate("/mensagem/@destinatario", root,XPathConstants.NODE)).getNodeValue());
        } catch (Exception e) {
            return 0;
        }         
    }    
    
    public static boolean isResponse(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return xpath.evaluate("/mensagem/respostas", root,XPathConstants.NODE) != null;
        } catch (Exception e) {
            return false;
        }
    }
    
    public static boolean isLendOrReturnRequest(String xml) {
        try {
            Node root = XmlUtil.getDocumentRoot(xml);
            XPath xpath = XPathFactory.newInstance().newXPath();        
            return xpath.evaluate("//solicitacao[count(emprestimo)+count(devolucao) > 0]", root,XPathConstants.NODE) != null;
        } catch (Exception e) {
            return false;
        }
    }    
    
}
